並不是說Reactive 一定要搭配Functional,只是搭配起來更好用,而後面介紹到的Reactor & WebFlux,基本上也都是Functional Programming,所以在這邊先介紹一下到底何謂Functional Programming。
函式語言程式設計(英語:functional programming)或稱函式程式設計、泛函編程,是一種編程範式,它將電腦運算視為函式運算,並且避免使用程式狀態以及易變物件。其中,λ演算為該語言最重要的基礎。而且,λ演算的函式可以接受函式作為輸入參數和輸出返回值。
上述源自於wiki,簡單的說Functional Programming就是前一天介紹的Programming paradigm其中宣告式的一種,所以她其實就是一種抽象的概念,盡量透過函式來編寫程式碼,會有以下幾個特性。
值可以指定給變數,也可以當作參數傳入方法(函數)中,則稱為一級值(first-class value
)。Java當中int、long、String或是物件等等都可以指定給變數並傳入方法(函數),這些也就是first-class value,而能夠指定給變數以及當作參數的函式,則被稱為First-class citizen
(一等公民), Java 8 之後,提供了Functions
、Suppliers
、Consumers
、Predicates
等等Functional Interfaces,Java 才終於有了First-class citizen。
java 有了First-class citizen之後,隨之而來就是higher-order function
,當一個函式(function)傳入一個或多個函式做為參數,他就是higher-order function,舉例來說,在操作Stream的時候常用到的map()
、filter()
、flatMap()
.......等都是higher-order function,他們都是將函式做為參數。
@Override
public Stream<R> filter(Predicate<? super R> predicate) {
return new StreamDecorator<R>( delegate.filter( predicate ), closeHandler );
}
@Override
public <R1> Stream<R1> map(Function<? super R, ? extends R1> mapper) {
return new StreamDecorator<>( delegate.map( mapper ), closeHandler );
}
@Override
public IntStream mapToInt(ToIntFunction<? super R> mapper) {
return new IntStreamDecorator(
delegate.mapToInt( mapper ),
closeHandler
);
}
同樣的input,一定會輸出相同的output。
大部分的說明都是沒有副作用,避免狀態或是資料改變,但現實中的企業應用專案,需要去log或是存入db資料,很難去做到完全的no side effects,所以追求最少的副作用是一個折衷的辦法。
不可更改,也就是當物件的狀態在創建後就不可以更動。
若遵守以上幾個條件,當需要多處理併發(Concurrency
)與多執行緒(Parallelism
)的時候,程式相對就可以單純許多,畢竟不會改變也就不用去synchronized
,而在維運的時候也不會到處去找BUG是否是因為某個狀態不如預期,可想而知這就是Functional Programming的優點之一。下面是一個簡單的將偶數乘上5並加總的範例。
List<Integer> data = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Integer sum = data
.stream()
.filter(i -> i % 2 == 0)
.map(i -> i * 5)
.reduce(0, Integer::sum);
System.out.println(sum);
//150
Java 本來的語言特性是更友善物件導向設計(OOP), OOP的特色就是萬般皆物件,用物件的概念去對應並設計程式,比較好入門而且更具體一點不像是Functional 這麼抽象,另外OOP的重點在於資料(DATA
),FP則關注於操作(operations
),所以有人說若是資料多操作少建議使用OOP,資料少操作多則推薦使用FP。我個人的觀點認為在JAVA中很難完全捨棄掉OOP,所以在OOP中去使用一些FP的寫法或許是一個不錯的辦法。